package com.mathdroid.modules;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;

import com.mathdroid.gui.main.SimulatorProgressFrame;
import com.mathdroid.model.EModelObserverEvent;
import com.mathdroid.model.IModelObserver;
import com.mathdroid.model.Model;
import com.mathdroid.model.enums.ESpec;
import com.mathdroid.model.items.Item;
import com.mathdroid.modules.sniper.ModuleSniper;

/**
 * This is a factory class. Depending on the character specialization different
 * method implementations are called.
 */
public final class ClassModuleFactory implements IModelObserver, Serializable {
	
	/**
	 * Generated UID.
	 */
	private static final long serialVersionUID = 1030540975085888231L;
	
	/**
	 * The calculator implementations / modules.
	 */
	private final HashMap<ESpec, Module> modules = 
		new HashMap<ESpec, Module>();
	
	/**
	 * The current active module for the current specialization.
	 */
	private Module activeModule = null;
	
	/**
	 * Create a new ClassModuleFactory.
	 */
	public ClassModuleFactory() {
		this.init();
		this.refreshModule();
		Model.registerObserver(this);
	}
	
	/**
	 * Creates all modules.
	 */
	private void init() {
		//TODO only sniper yet
		Module sniper = new ModuleSniper();
		this.modules.put(ESpec.SNIPER, sniper);
	}

	@Override
	public void modelChanged(final EModelObserverEvent e) {
		
		/* On specialization change the calculator has to change. */
		if (e == EModelObserverEvent.PROFILE_LOADED) {
			this.refreshModule();
		}
		
		/* Some events do _NOT_ require a new rating of items. */
		if (e != EModelObserverEvent.ITEM_BROWSER_MODEL_CHANGED) {
			this.rateItems(Model.getProfile().getEquipedItems().values());
		}
	}
	
	/**
	 * Sets the active module for the current specialization.
	 */
	private void refreshModule() {
		this.activeModule = this.modules.get(Model.getESpec());
	}

	/**
	 * Rate the items.
	 * @param t Items to rate.
	 */
	public void rateItems(final Collection<Item> t) {
		for (Item i : t) {
			i.setRating(Math.random());
		}
	}

	/**
	 * Start a new simulation.
	 * @param i Iterations.
	 */
	public void simulate(final int i) {
		final Simulator s = new Simulator(i, this.activeModule);
		final int maxProgress = 100;
		final SimulatorProgressFrame f = 
			new SimulatorProgressFrame(s, 0, maxProgress, "Simulation");
		s.addPropertyChangeListener(f);
		s.execute();
	}
}
